package com.xyq.fs.scan;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;

import java.util.HashSet;

import java.util.Set;
import java.util.concurrent.ExecutorService;

import java.util.concurrent.TimeUnit;

import com.xyq.fs.base.MyDirectoryS;
import com.xyq.fs.constants.IndexStringConstants;
import com.xyq.fs.constants.NoIndexNamesConstant;
import com.xyq.fs.constants.ParseConstant;

import com.xyq.fs.index.IndexFileInf;

import com.xyq.fs.task.MyTask;

import com.xyq.fs.views.WindowsGo;

import javafx.application.Platform;

/**
 * 扫描文件接口 1.可开始,可暂停
 * 
 * @author xyqq
 *
 */
public class ScanFileImpl implements FileVisitor<Path> {

	// C盘只扫描用户文件夹

	ExecutorService pool;

	private int bai = 100;
	private static FileTime ONE = FileTime.fromMillis(1);

	// private boolean simpleScan;
	//
	// public boolean isSimpleScan() {
	// return simpleScan;
	// }
	//
	// public void setSimpleScan(boolean simpleScan) {
	// this.simpleScan = simpleScan;
	// }

	/***
	 * 
	 * @param pool
	 * @param fileType
	 *            扫描或搜索什么类型的文件
	 */
	public ScanFileImpl(ExecutorService pool) {

		this.pool = pool;
	}

	int tempnum = 1;

	MyTask my = new MyTask(null, null, null, -1, false);

	File file;

	// 不扫描
	Set<String> noIndexSuffixSet = new HashSet<>();

	@Override
	public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {

		// C盘只扫描user文件夹

		if (NoIndexNamesConstant.WINDOWS.equals(dir) || NoIndexNamesConstant.PerfLogs.equals(dir)
				|| NoIndexNamesConstant.ProgramFiles.equals(dir) || NoIndexNamesConstant.ProgramFiles86.equals(dir)
				|| NoIndexNamesConstant.LOCAL.equals(dir) || NoIndexNamesConstant.ProgramData.equals(dir)
				|| NoIndexNamesConstant.M2.equals(dir)) {
			System.out.println("跳过：" + dir);
			return FileVisitResult.SKIP_SUBTREE;
		}

		// 只有完全模式开启式时,并且选中文件夹时
		if (!WindowsGo.rbtnB.isSelected() && WindowsGo.cboxA.getValue().equals(IndexStringConstants.QT2)) {
			if (WindowsGo.rbtnA.isSelected() || attrs.lastAccessTime().equals(ONE)) {

				IndexFileInf iff = null;
				iff = ParseConstant.idn;
				file = dir.toFile();
				String fname = file.getName().toUpperCase();
				my.setUpFileName(fname);
				my.setIff(iff);
				my.setFile(file);
				try {
					pool.submit(my).get(WindowsGo.TASK_TIME, TimeUnit.SECONDS);
				} catch (Exception e1) {
					e1.printStackTrace();
					System.out.println(file + "在指定时间内没有索引完,任务放弃");
				}
				try {
					Files.setAttribute(dir, IndexStringConstants.LASTACCTIME, ONE);
					tempnum++;
					Platform.runLater(() -> {
						WindowsGo.tsB.setText(IndexStringConstants.YSM + tempnum);
					});
					if (tempnum / bai > 1) {
						bai += 100;
						MyDirectoryS.updateReaderAndSearcher();
					}
				} catch (IOException e) {
				}
				fname = null;
			}
		}

		dir = null;
		attrs = null;
		file = null;
		return FileVisitResult.CONTINUE;
	}

	@Override
	public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {

		if (WindowsGo.SLEEP_NOW == 4)
			return FileVisitResult.TERMINATE;

		// 根据最后访问时间确实文件是否需要被索引
		if (WindowsGo.rbtnA.isSelected() || !attrs.lastAccessTime().equals(ONE)) {

			while (WindowsGo.SLEEP_NOW == 2) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			file = path.toFile();
			String fname = file.getName().toUpperCase();
			int dian = fname.lastIndexOf(IndexStringConstants.DIAN);
			if (dian == -1)
				return FileVisitResult.CONTINUE;
			String suffix = fname.substring(dian);
			if (noIndexSuffixSet.contains(suffix)) {
				return FileVisitResult.CONTINUE;
			}
			long size = file.length();
			if (size == 0)
				return FileVisitResult.CONTINUE;

			// 如果当前文件名和大小与缓存的跳过相同，就继续跳过
			if (WindowsGo.skipFilesMap.contains(file.getAbsolutePath())) {
				return FileVisitResult.CONTINUE;
			}

			char tou = fname.charAt(0);
			if (tou != NoIndexNamesConstant.DAO && tou != NoIndexNamesConstant.PIE
					&& fname.indexOf(NoIndexNamesConstant.LUCENE) == -1) {
				IndexFileInf iff = null;
				switch (WindowsGo.cboxA.getValue()) {
				case IndexStringConstants.QBLX:
					if (WindowsGo.rbtnB.isSelected())
						iff = ParseConstant.PARSE_MAP_SIMPLE.get(suffix);
					else
						iff = ParseConstant.PARSE_MAP.get(suffix);
					break;
				case IndexStringConstants.QT:
					iff = ParseConstant.PARSE_MAP_OTHER.get(suffix);
					break;
				default:
					if (suffix.equals(WindowsGo.cboxA.getValue()))
						iff = ParseConstant.PARSE_MAP.get(suffix);
					break;
				}

				if (iff != null) {

					// //每100提交一次
					if (tempnum / bai > 1) {
						bai += 100;
						MyDirectoryS.updateReaderAndSearcher();
						// System.out.println("提交了" + tempnum);
					}
					my.setUpFileName(fname);
					my.setIff(iff);
					my.setFile(file);
					my.setSuffix(suffix);

					try {
						pool.submit(my).get(WindowsGo.TASK_TIME, TimeUnit.SECONDS);
					} catch (Exception e1) {
						WindowsGo.skipFilesMap.add(file.getAbsolutePath());
						System.out.println(file + "在指定时间内没有索引完,任务放弃");
					}
					try {
						Files.setAttribute(path, IndexStringConstants.LASTACCTIME, ONE);
						tempnum++;
						/* 把结果显示到UI */
						Platform.runLater(() -> {
							WindowsGo.tsB.setText(IndexStringConstants.YSM + tempnum);
						});
					} catch (IOException e) {
						System.out.println("同步失败:" + path);
					}
				} else {
					noIndexSuffixSet.add(suffix);
					return FileVisitResult.CONTINUE;
				}
				fname = null;
				path = null;
				attrs = null;
				file = null;
				suffix = null;
			}
		}

		return FileVisitResult.CONTINUE;
	}

	@Override
	public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {

		file = null;
		exc = null;
		return FileVisitResult.CONTINUE;
	}

	@Override
	public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {

		dir = null;
		exc = null;
		return FileVisitResult.CONTINUE;
	}

	public static void main(String[] args) throws IOException {

	}

}
